#pragma once
#include "can.hpp"
#include "canopen.hpp"
#include <functional>
#include <map>
namespace CANalyst2
{

  class CANDispatch
  {
  private:
    struct CanCallback
    {
      int tick;
      int interval;
      std::function<void(void)> timeout;
      std::function<void(const CanStamped &)> callback;
    };
    std::shared_ptr<CANStream> can; // 底层CAN设备对象（负责收发）
    std::shared_ptr<CANOPEN> coe;   // CANopen协议处理对象
    std::map<uint32_t, CanCallback> callbacks; // 按CAN ID处理回调
    std::vector<CanStamped> buffer_send0; // ch0待发送队列
    std::vector<CanStamped> buffer_send1; // ch1待发送队列
    int index; 
    bool is_valid = false;   

  public:
    CANDispatch(const std::string &dev, CanBaud baud, int can_ind);
    ~CANDispatch();
    inline void Register(uint32_t id,
                         std::function<void(const CanStamped &)> cbk,
                         int cnts = -1,
                         std::function<void(void)> timeout = NULL)
    {
      if (callbacks.find(id) != callbacks.end())
      {
        std::cout << "can id overlap, "
                  << "some devcie can_id confict" << std::endl;
        raise(SIGABRT);
      }

      CanCallback t;
      t.interval = cnts;
      t.tick = 0;
      t.timeout = timeout;
      t.callback = cbk;
      callbacks[id] = t;
    }

    inline void Write(int ch, const CanStamped &frame) 
    {
      if (ch == 0) {
        buffer_send0.emplace_back(frame); 
      } 
      else if (ch == 1){
        buffer_send1.emplace_back(frame); 
      }
    }
    inline CANOPEN &COE() { return *(coe.get()); }
    inline bool Valid() { return can != NULL; }
    void send_msg(int ch);
    void send_msg(int ch, CanStamped &frame);
    void recv_msg(int ch);
    void recv_msg(int ch, CanStamped &frame);
    void Update(int ch);
    void Update2(int ch,int s_time);
    inline bool valid() { return is_valid; }
    inline void clr_send_buffer(int ch) { 
      if (ch == 0) {
        buffer_send0.clear(); 
      }
      else if (ch == 1) {
        buffer_send1.clear();
      }
    }
  };

  class CANProcess
  {
  public:
    static std::map<std::string, std::function<std::shared_ptr<CANProcess>()>> *impls;
    static std::vector<std::shared_ptr<CANDispatch>> cans;

    virtual int Update() = 0;
  };
} // namespace drivers
